/*
 * Agence.java
 *
 * Created on 16 mai 2007, 09:51
 */

package bibliotheque.server.gui;

import bibliotheque.nameserver.remote.NameServerRemoteIS;
import bibliotheque.events.ErrorOccuredEvent;
import bibliotheque.events.ErrorOccuredListener;
import bibliotheque.events.StateChangedEvent;
import bibliotheque.events.StateChangedListener;
import bibliotheque.server.*;
import java.io.File;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.util.concurrent.Semaphore;
import javax.swing.JDialog;
import javax.swing.JFileChooser;

/**
 *
 * @author  guillaume
 */
public class ServerGui extends javax.swing.JFrame implements StateChangedListener,ErrorOccuredListener {

    //Le rafraichissement des services utilisable disponible se fait en temps reel
    //lorsque l'utilisateur �crit dans les champs sp�cifiant l'emplacement du RMIRegistry.
    //Comme la m�thode registry.list est bloquante pendant plusieurs secondes si l'emplacement n'est pas valable,
    //on a mis en place un syst�me qui permet d'interrompre les rafraissements au fur et � mesure de la frappe au clavier.
    
    private class ThreadService extends Thread {
        public void run() {
            Registry registry;
            String[] listbound;
            try {
                //Le s�maphore mutex_service1 prot�ge la section critique qui permet d'interrompre le rafraichissement courant.
                //Le s�maphore mutex_service2 prot�ge la variable thread_service et oblige les rafraichissements qui ont �t� interrompus � quitter.
                mutex_service1.acquireUninterruptibly();
                    if(thread_service != null) thread_service.interrupt();
                    mutex_service2.acquire();
                    thread_service = this;
                    mutex_service2.release();
                mutex_service1.release();
                
                //On d�fini un certain nombre de sections critiques.
                //Le rafraichissement tente de prendre le s�maphore mutex_service2 au d�but de chacune de ces sections critiques.
                //Si le rafraichissement a �t� interrompu, le rafraichissement s'arr�te sur une InterruptedException.
                mutex_service2.acquire();
                jComboBoxServices.removeAllItems();
                jComboBoxServices.addItem("Refreshing...");
                mutex_service2.release();
                
                registry = LocateRegistry.getRegistry(jTextFieldRmiAddress.getText(),Integer.parseInt(jTextFieldRmiPort.getText()));
                listbound = registry.list();
                
                mutex_service2.acquire();
                jComboBoxServices.removeAllItems();
                mutex_service2.release();
                
                for(int i=0 ; i < listbound.length ; i++){
                    if (registry.lookup(listbound[i]) instanceof NameServerRemoteIS) {
                        mutex_service2.acquire();
                        jComboBoxServices.addItem(listbound[i]);
                        mutex_service2.release();
                    }
                }
                
                mutex_service2.acquire();
                thread_service = null;
                EnableUpdate();
                mutex_service2.release();
            } catch (InterruptedException ex) {
                
            } catch (Exception ex) {
                try {
                    mutex_service2.acquire();
                    jComboBoxServices.removeAllItems();
                    mutex_service2.release();
                } catch (InterruptedException ex2) {
                    
                }
            }
        }
    }
    
    private Server agence;
    private Semaphore mutex_service1;
    private Semaphore mutex_service2;
    private ThreadService thread_service;
    
    /** Creates new form Agence */
    public ServerGui() {
        this.mutex_service1 = new Semaphore(1);
        this.mutex_service2 = new Semaphore(1);
        this.setTitle("Server");
        initComponents();
        new ThreadService().start();
    }
    
    private void EnableUpdate() {
        this.jButtonStopService.setEnabled(!this.jLabelEtat.getText().startsWith("STOP"));
        this.jButtonStartService.setEnabled(
                this.jLabelEtat.getText().equals("STOP") &&
                this.jComboBoxServices.getSelectedItem() != null &&
                !this.jTextFieldIdentifiant.getText().equals("")&&
                new File(this.jTextFieldConfigurationFilePath.getText()).exists());
        this.jButtonBrowse.setEnabled(this.jLabelEtat.getText().equals("STOP"));
        this.jTextFieldIdentifiant.setEnabled(this.jLabelEtat.getText().equals("STOP"));
        this.jTextFieldRmiAddress.setEnabled(this.jLabelEtat.getText().equals("STOP"));
        this.jTextFieldRmiPort.setEnabled(this.jLabelEtat.getText().equals("STOP"));
        this.jTextFieldConfigurationFilePath.setEnabled(this.jLabelEtat.getText().equals("STOP"));
        this.jComboBoxServices.setEnabled(this.jLabelEtat.getText().equals("STOP"));
    }
    
    public void StateChanged(StateChangedEvent event) {
        this.jLabelEtat.setText(event.GetState());
        this.EnableUpdate();
    }
    
    public void ErrorOccured(ErrorOccuredEvent event) {
        this.jTextAreaConsole.append(event.GetError() + "\n");
    }
    
    // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
    private void initComponents() {
        jLabel1 = new javax.swing.JLabel();
        jButtonStartService = new javax.swing.JButton();
        jButtonStopService = new javax.swing.JButton();
        jComboBoxServices = new javax.swing.JComboBox();
        jLabelEtat = new javax.swing.JLabel();
        jTextFieldIdentifiant = new javax.swing.JTextField();
        jLabel2 = new javax.swing.JLabel();
        jLabel3 = new javax.swing.JLabel();
        jLabel4 = new javax.swing.JLabel();
        jTextFieldConfigurationFilePath = new javax.swing.JTextField();
        jButtonBrowse = new javax.swing.JButton();
        jLabel5 = new javax.swing.JLabel();
        jLabel6 = new javax.swing.JLabel();
        jTextFieldRmiAddress = new javax.swing.JTextField();
        jTextFieldRmiPort = new javax.swing.JTextField();
        jScrollPane1 = new javax.swing.JScrollPane();
        jTextAreaConsole = new javax.swing.JTextArea();
        jButtonRefresh = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setResizable(false);
        addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowClosing(java.awt.event.WindowEvent evt) {
                formWindowClosing(evt);
            }
        });

        jLabel1.setText("Etat :");

        jButtonStartService.setText("Start");
        jButtonStartService.setEnabled(false);
        jButtonStartService.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButtonStartServiceActionPerformed(evt);
            }
        });

        jButtonStopService.setText("Stop");
        jButtonStopService.setEnabled(false);
        jButtonStopService.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButtonStopServiceActionPerformed(evt);
            }
        });

        jLabelEtat.setText("STOP");
        jLabelEtat.setBorder(new javax.swing.border.LineBorder(new java.awt.Color(0, 0, 0), 2, true));

        jTextFieldIdentifiant.addCaretListener(new javax.swing.event.CaretListener() {
            public void caretUpdate(javax.swing.event.CaretEvent evt) {
                jTextFieldIdentifiantCaretUpdate(evt);
            }
        });

        jLabel2.setText("Identifiant du serveur :");

        jLabel3.setText("Service :");

        jLabel4.setText("Fichier de configuration :");

        jTextFieldConfigurationFilePath.addCaretListener(new javax.swing.event.CaretListener() {
            public void caretUpdate(javax.swing.event.CaretEvent evt) {
                jTextFieldConfigurationFilePathCaretUpdate(evt);
            }
        });

        jButtonBrowse.setText("Browse");
        jButtonBrowse.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButtonBrowseActionPerformed(evt);
            }
        });

        jLabel5.setText("Adresse du rmiregistry :");

        jLabel6.setText("port du rmiregistry :");

        jTextFieldRmiAddress.setText("127.0.0.1");
        jTextFieldRmiAddress.addCaretListener(new javax.swing.event.CaretListener() {
            public void caretUpdate(javax.swing.event.CaretEvent evt) {
                jTextFieldRmiAddressCaretUpdate(evt);
            }
        });

        jTextFieldRmiPort.setText("2222");
        jTextFieldRmiPort.addCaretListener(new javax.swing.event.CaretListener() {
            public void caretUpdate(javax.swing.event.CaretEvent evt) {
                jTextFieldRmiPortCaretUpdate(evt);
            }
        });

        jTextAreaConsole.setColumns(20);
        jTextAreaConsole.setRows(5);
        jTextAreaConsole.setEnabled(false);
        jScrollPane1.setViewportView(jTextAreaConsole);

        jButtonRefresh.setText("Refresh");
        jButtonRefresh.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButtonRefreshActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addContainerGap()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addGroup(layout.createSequentialGroup()
                                .addComponent(jLabel3)
                                .addGap(27, 27, 27)
                                .addComponent(jComboBoxServices, javax.swing.GroupLayout.PREFERRED_SIZE, 151, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(jButtonRefresh))
                            .addGroup(layout.createSequentialGroup()
                                .addComponent(jLabel2)
                                .addGap(7, 7, 7)
                                .addComponent(jTextFieldIdentifiant, javax.swing.GroupLayout.DEFAULT_SIZE, 432, Short.MAX_VALUE))
                            .addGroup(layout.createSequentialGroup()
                                .addComponent(jLabel5)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(jTextFieldRmiAddress, javax.swing.GroupLayout.DEFAULT_SIZE, 432, Short.MAX_VALUE))
                            .addGroup(layout.createSequentialGroup()
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                    .addComponent(jLabel6)
                                    .addComponent(jLabel4))
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                    .addGroup(layout.createSequentialGroup()
                                        .addComponent(jTextFieldConfigurationFilePath, javax.swing.GroupLayout.DEFAULT_SIZE, 355, Short.MAX_VALUE)
                                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                        .addComponent(jButtonBrowse))
                                    .addComponent(jTextFieldRmiPort, javax.swing.GroupLayout.DEFAULT_SIZE, 428, Short.MAX_VALUE)))))
                    .addGroup(layout.createSequentialGroup()
                        .addGap(89, 89, 89)
                        .addComponent(jButtonStartService, javax.swing.GroupLayout.PREFERRED_SIZE, 73, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(138, 138, 138)
                        .addComponent(jButtonStopService, javax.swing.GroupLayout.PREFERRED_SIZE, 72, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addGroup(layout.createSequentialGroup()
                        .addContainerGap()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addGroup(layout.createSequentialGroup()
                                .addComponent(jLabel1)
                                .addGap(32, 32, 32)
                                .addComponent(jLabelEtat, javax.swing.GroupLayout.DEFAULT_SIZE, 492, Short.MAX_VALUE))
                            .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 551, Short.MAX_VALUE))))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel3)
                    .addComponent(jComboBoxServices, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jButtonRefresh))
                .addGap(15, 15, 15)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel2)
                    .addComponent(jTextFieldIdentifiant, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel5)
                    .addComponent(jTextFieldRmiAddress, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel6)
                    .addComponent(jTextFieldRmiPort, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel4)
                    .addComponent(jTextFieldConfigurationFilePath, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jButtonBrowse))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jButtonStartService)
                    .addComponent(jButtonStopService))
                .addGap(14, 14, 14)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel1)
                    .addComponent(jLabelEtat))
                .addGap(14, 14, 14)
                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 102, Short.MAX_VALUE)
                .addContainerGap())
        );
        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void jButtonRefreshActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonRefreshActionPerformed
        new ThreadService().start();
    }//GEN-LAST:event_jButtonRefreshActionPerformed

    private void formWindowClosing(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowClosing
        JDialog dialog = new JDialog(this, "Waiting for the Server to stop...");
        dialog.setSize(300,50);
        dialog.setLocation(50,50);
        dialog.setLocationRelativeTo(this);
        dialog.setVisible(true);
        if(this.agence != null) this.agence.StopService();
        while(!this.jLabelEtat.getText().equals("STOP"));
    }//GEN-LAST:event_formWindowClosing

    private void jTextFieldConfigurationFilePathCaretUpdate(javax.swing.event.CaretEvent evt) {//GEN-FIRST:event_jTextFieldConfigurationFilePathCaretUpdate
        this.EnableUpdate();
    }//GEN-LAST:event_jTextFieldConfigurationFilePathCaretUpdate

    private void jTextFieldRmiPortCaretUpdate(javax.swing.event.CaretEvent evt) {//GEN-FIRST:event_jTextFieldRmiPortCaretUpdate
        new ThreadService().start();
    }//GEN-LAST:event_jTextFieldRmiPortCaretUpdate

    private void jTextFieldRmiAddressCaretUpdate(javax.swing.event.CaretEvent evt) {//GEN-FIRST:event_jTextFieldRmiAddressCaretUpdate
        new ThreadService().start();
    }//GEN-LAST:event_jTextFieldRmiAddressCaretUpdate
                
    private void jTextFieldIdentifiantCaretUpdate(javax.swing.event.CaretEvent evt) {//GEN-FIRST:event_jTextFieldIdentifiantCaretUpdate
        this.setTitle("Server " + this.jTextFieldIdentifiant.getText());
        this.EnableUpdate();
    }//GEN-LAST:event_jTextFieldIdentifiantCaretUpdate
    
    private void jButtonBrowseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonBrowseActionPerformed
        JFileChooser filechooser = new JFileChooser();
        filechooser.addChoosableFileFilter(new XSCFilter());
        filechooser.setCurrentDirectory(new File("./src/bibliotheque/config"));
        if (filechooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
            this.jTextFieldConfigurationFilePath.setText(filechooser.getSelectedFile().toString());
        }
    }//GEN-LAST:event_jButtonBrowseActionPerformed
    
    private void jButtonStopServiceActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonStopServiceActionPerformed
        this.agence.StopService();
    }//GEN-LAST:event_jButtonStopServiceActionPerformed
    
    private void jButtonStartServiceActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonStartServiceActionPerformed
        try {
            this.agence = new Server(this.jTextFieldIdentifiant.getText());
            this.agence.AddStateChangedListener(this);
            this.agence.AddErrorOccuredListener(this);
            this.agence.StartService(new File(this.jTextFieldConfigurationFilePath.getText()), this.jComboBoxServices.getSelectedItem().toString(), this.jTextFieldRmiAddress.getText(), Integer.parseInt(this.jTextFieldRmiPort.getText()));
        } catch (Exception ex) {
            ex.printStackTrace();
        }  
    }//GEN-LAST:event_jButtonStartServiceActionPerformed
    
    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new ServerGui().setVisible(true);
            }
        });
    }
    
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton jButtonBrowse;
    private javax.swing.JButton jButtonRefresh;
    private javax.swing.JButton jButtonStartService;
    private javax.swing.JButton jButtonStopService;
    private javax.swing.JComboBox jComboBoxServices;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JLabel jLabel5;
    private javax.swing.JLabel jLabel6;
    private javax.swing.JLabel jLabelEtat;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JTextArea jTextAreaConsole;
    private javax.swing.JTextField jTextFieldConfigurationFilePath;
    private javax.swing.JTextField jTextFieldIdentifiant;
    private javax.swing.JTextField jTextFieldRmiAddress;
    private javax.swing.JTextField jTextFieldRmiPort;
    // End of variables declaration//GEN-END:variables
    
}
